package indv.Cning.cfengsecuritydemo.service;

import indv.Cning.cfengsecuritydemo.entity.TAuthority;
import indv.Cning.cfengsecuritydemo.entity.TRole;
import indv.Cning.cfengsecuritydemo.entity.Tuser;
import indv.Cning.cfengsecuritydemo.repository.TuserRepository;
import lombok.RequiredArgsConstructor;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;

/**
 * @author Cfeng
 * @date 2022/7/21
 * 用户登录的Service由spring security定义，we只需要实现该接口，调用userRepository实现
 */

@RequiredArgsConstructor
@Service
public class UserDetailServiceImpl implements UserDetailsService {

    private final TuserRepository userRepository;

    //默认就是用户名-密码模式
    //认证和授权一起完成，框架自动调用
    @Override
    @Transactional
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        Tuser tuser = userRepository.findByUserName(username);
        if(tuser == null) {
            throw new UsernameNotFoundException("用户名不存在");
        }
        return new User(tuser.getUserName(),tuser.getUserPwd(),this.getAuthorities(tuser));
    }

    //授权的业务方法
    private List<GrantedAuthority> getAuthorities(Tuser tuser) {
        //获取用户的角色权限，就是之前Shiro的Realm中完成的事情，上面返回的User就类似一个Subject,为系统的用户
        //上面查询数据库完成认证，该方法完成授权，这样最后就是一个完整的用户，shiro是分开的，认证只是返回了principa，授权中再将principal和权限绑定
        List<GrantedAuthority> authorities = new ArrayList<>();
        //将角色加入权限集合中
        for(TRole role : tuser.getRoles()) {
            authorities.add(new SimpleGrantedAuthority("ROLE_" + role.getRoleName()));
            //角色对应的权限
            for(TAuthority authority : role.getAuthorities()) {
                authorities.add(new SimpleGrantedAuthority(authority.getAuthName()));
            }
//            role.getAuthorities().stream().forEach(authority -> authorities.add(new SimpleGrantedAuthority(authority.getAuthName())));
        }
        return authorities;
    }
}
